<?php

namespace app\utils;

use Aws\CommandInterface;
use Aws\Exception\AwsException;
use Aws\S3\Exception\S3Exception;
use Aws\S3\MultipartUploader;
use Aws\S3\S3Client;

//官方文档：https://docs.aws.amazon.com/zh_cn/sdk-for-php/v3/developer-guide/welcome.html
//安装依赖: composer require aws/aws-sdk-php
class AWSLoader
{

    private $key, $secret;
    private $preUpNum, $preDownNum;

    public function __construct($key, $secret)
    {
        $this->key = $key;
        $this->secret = $secret;
    }

    public function upload($localFilePath, $remoteFolder, $publicDownload, $region, $bucket, $onProgressCallback)
    {
        $client = new S3Client([
            'region' => $region,
            'version' => 'latest',
            'credentials' => ['key' => $this->key, 'secret' => $this->secret],
            'http' => ['verify' => config('app.ca_pem_path')],
        ]);
        try {
            $this->preUpNum = -1;
            $uploader = new MultipartUploader($client, $localFilePath, [
                    //'ACL' => $publicDownload ? 'public-read' : 'private', //这个请求需要特殊授权否则上传失败
                    'bucket' => $bucket,
                    'key' => $remoteFolder === '' ? basename($localFilePath) : ($remoteFolder . '/' . basename($localFilePath)),
                    'part_size' => 1024 * 1024 * 1024, //分段设置足够大，目的是不分段，避免多个分段进度同时回调导致进度数值错乱
                    'before_upload' => function (CommandInterface $cmd) use ($onProgressCallback) {
                        $cmd['@http']['progress'] = function ($downloadTotal, $downloaded, $uploadTotal, $uploaded) use ($onProgressCallback) {
                            if ($onProgressCallback && $uploadTotal > 0 && $uploaded < $uploadTotal) {
                                $progress = (int)floor(100 * $uploaded / $uploadTotal);
                                if ($this->preUpNum != $progress) {
                                    $onProgressCallback($progress);
                                    $this->preUpNum = $progress;
                                }
                            }
                        };
                    },
                ]
            );
            $uploader->upload();
            echo "文件上传成功！\n";
            if ($onProgressCallback) {
                $onProgressCallback(100);
            }
        } catch (S3Exception $e) {
            echo "文件上传失败: " . $e->getMessage() . "\n";
        } catch (AwsException $e) {
            echo "文件上传失败: " . $e->getMessage() . "\n";
        }
    }

    public function download($remoteFolder, $fileName, $savePath, $region, $bucket, $onProgressCallback)
    {
        $client = new S3Client([
            'region' => $region,
            'version' => 'latest',
            'credentials' => ['key' => $this->key, 'secret' => $this->secret],
            'http' => ['verify' => config('app.ca_pem_path')],
        ]);
        try {
            $this->preDownNum = -1;
            $client->getObject([
                'Bucket' => $bucket,
                'Key' => $remoteFolder === '' ? $fileName : ($remoteFolder . '/' . $fileName),
                'SaveAs' => $savePath,
                '@http' => [
                    'progress' => function ($downloadTotal, $downloaded, $uploadTotal, $uploaded) use ($onProgressCallback) {
                        if ($onProgressCallback && $downloadTotal > 0 && $downloaded < $downloadTotal) {
                            $progress = (int)floor(100 * $downloaded / $downloadTotal);
                            if ($this->preDownNum != $progress) {
                                $onProgressCallback($progress);
                                $this->preDownNum = $progress;
                            }
                        }
                    },
                ],
            ]);
            echo "文件下载成功！\n";
            if ($onProgressCallback) {
                $onProgressCallback(100);
            }
        } catch (S3Exception $e) {
            echo "文件下载失败: " . $e->getMessage() . "\n";
        } catch (AwsException $e) {
            echo "文件下载失败: " . $e->getMessage() . "\n";
        }
    }

}